#include "Threadpool.hpp"

#include <unistd.h>
#include <stdio.h>

namespace wd
{

Threadpool::Threadpool(int threadNum , int queSize)
: _threads() // vector 的无参构造函数没有开辟空间
, _threadNum(threadNum)
, _queSize(queSize)
, _taskque(_queSize)
, _isExit(false)
{
    // 提前准备好空间
    _threads.reserve(_threadNum);
}

void Threadpool::start()
{
    for(int i = 0 ; i < _threadNum ; ++i)
    {
        //创建N个子线程对象WorkerThread
        //将线程池的doTask方法注册给线程对象
        unique_ptr<Thread> up(new Thread(std::bind(&Threadpool::doTask , this)));
        // 存入数组中，up 是一个左值必须转换成右值才能转移到容器中
        _threads.push_back(std::move(up));
    }

    // 让每一个子线程运行起来
    for(auto & pthread : _threads)
    {
        pthread -> start();
    }
}

void Threadpool::addTask(Task && task)
{
    if(task)
    {
        _taskque.push(std::move(task));
    }
}

// 停止线程池的运行
void Threadpool::stop()
{
    // 当任务队列中还有任务时
    // 暂时不退出，等待任务执行完毕
    while(!_taskque.empty())
    {
        sleep(1);
    }

    // 修改退出的标志位
    _isExit = true;

    // 通知所有的子线程从 wait 中醒来
    _taskque.wakeup();

    printf("\n线程池开始连接子线程\n");

    // 回收每一个子线程
    for(auto & pthread : _threads)
    {
        pthread -> join();
    }
}

void Threadpool::doTask()
{
    // 当子循环退出 while 循环时，子线程就会结束运行
    while(!_isExit)
    {
        // 每一个子线程都要从任务队列中获取任务并执行
        Task task = _taskque.pop();

        if(task)
        {
            // 执行任务
            task();

        }
    }
}

} // end of namespace wd
